package com.shengwei.truck.driver.view.ui.app;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.text.TextUtils;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer;
import com.lzy.okhttputils.OkHttpUtils;
import com.lzy.okhttputils.cookie.store.MemoryCookieStore;
import com.lzy.okhttputils.cookie.store.PersistentCookieStore;
import com.lzy.okhttputils.model.HttpParams;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.UsingFreqLimitedMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.utils.StorageUtils;
import com.shengwei.truck.driver.R;
import com.shengwei.truck.driver.third_sdk.baidu.LocationService;
import com.shengwei.truck.driver.socket.SocketManager;
import com.shengwei.truck.driver.utils.DateTimeUtils;
import com.shengwei.truck.driver.utils.MyLogCat;
import com.shengwei.truck.driver.utils.MyLogFile;
import com.shengwei.truck.driver.utils.NotificationUtils;
import com.shengwei.truck.driver.utils.SPUtils;
import com.shengwei.truck.driver.view.ui.ActivityCollectorUtil;
import com.umeng.commonsdk.UMConfigure;

import org.greenrobot.eventbus.EventBus;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import cn.jpush.android.api.JPushInterface;

/**
 * 管理整个APP的生命周期
 */
public class MyApplication extends Application {
    private static String mIsUplocation;
    private static String mWeighsStatus;
    String TAG = "MyApplication";
    public static MyApplication instance;
    public static Context mContext;
    //选择（拍照）图片相关
    public static final String PIC_DIRECTORY = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ATruckDriver/TakePhotoPic";  //相机拍照后，图片保存的目录名
    //定位相关
    public static LocationService mLocationService;
    private NotificationUtils mNotificationUtils;
    private double mLat;
    private double mLng;
    public static int UPDATE_STATE = 0; //APP是否已经正在更新，0未更新，1正在更新

    //当前正在进行的任务ID
    public static String mCurTaskId;

    public static synchronized MyApplication getInstance() {
        if(instance == null) {
            instance = new MyApplication();
        }
        return instance;
    }

    @Override
    public void onCreate() {
        String processName = this.getProcessName(this, android.os.Process.myPid());
        MyLogFile.e(TAG,"processName:"+processName);
        if("com.shengwei.truck.driver".equals(processName)) { //保证地图SDK等只初始化一次
            closeAndroidPDialog();
            initBaiduLoc();
            initJpush();
            initImageLoader(getApplicationContext());
            recvBroadNetChange();
            initOkHttp();
            initUM();

        }
        super.onCreate();
    }

    private void initUM() {
        UMConfigure.init(getApplicationContext(),"606fafb6de41b946ab437e01","truckDriverForAndroid",UMConfigure.DEVICE_TYPE_PHONE,null);
        UMConfigure.setLogEnabled(true);
    }

    private void initJpush() {
        JPushInterface.setDebugMode(true);
        JPushInterface.init(this);
    }

    /**
     * 初始化OkHttpUtils图片加载框架
     */
    private  void initOkHttp() {
    /*  公共参数
        HttpHeaders headers = new HttpHeaders();
        headers.put("commonHeaderKey1", "commonHeaderValue1");    //所有的 header 都 不支持 中文
        headers.put("commonHeaderKey2", "commonHeaderValue2");
        HttpParams params = new HttpParams();
        params.put("commonParamsKey1", "commonParamsValue1");     //所有的 params 都 支持 中文
        params.put("commonParamsKey2", "这里支持中文参数");
     */
        String auth =  "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJnYW94aWFvd2VpIiwiY3JlYXRlZCI6MTYxNTk3NjI2OTM3OSwiZXhwIjoxNjE2NTgxMDY5fQ.fSbulkKEXWyNaEIGm7HukTne1d4x1seRPIOmVj1wnA8";

        //必须调用初始化
        OkHttpUtils.init(this);
        //以下都不是必须的，根据需要自行选择
        OkHttpUtils.getInstance()//
                .debug("OkHttpUtils")//是否打开调试
                .setConnectTimeout(OkHttpUtils.DEFAULT_MILLISECONDS)               //全局的连接超时时间
                .setReadTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS)                  //全局的读取超时时间
                .setWriteTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS)                //全局的写入超时时间
                .setCookieStore(new MemoryCookieStore())                          //cookie使用内存缓存（app退出后，cookie消失）
                .setCookieStore(new PersistentCookieStore())                      //cookie持久化存储，如果cookie不过期，则一直有效
           .addCommonParams(new HttpParams("Authorization",auth)) ;                                      //设置全局公共头
        //GXW-  .addCommonParams(params);
    }


    /**
     * 监听网络断开广播
     */
    private void recvBroadNetChange() {
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        NetworkChange networkChange = new NetworkChange();
        registerReceiver(networkChange , filter);
    }

    /**
     * 根据进程ID pid得到进程名
     * @param cxt
     * @param pid 进程ID
     * @return  String进程名
     */
    public static String getProcessName(Context cxt, int pid) {
        ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
        if (runningApps == null) {
            return null;
        }
        for (ActivityManager.RunningAppProcessInfo procInfo : runningApps) {
            if (procInfo.pid == pid) {
                return procInfo.processName;
            }
        }
        return null;
    }

    /**
     * 初始化百度定位SDK
     */
    private void initBaiduLoc() {
        //只要打开了APP程序就立即定位
        mLocationService = new LocationService(getApplicationContext());
        SDKInitializer.initialize(getApplicationContext());
        SDKInitializer.setCoordType(CoordType.BD09LL);
        mLocationService.registerListener(mListener);
        MyLogFile.i(TAG,"initBaiduLoc END");
    }
    /**
     * 开启定位
     */
    public static void startLocService() {
        if(MyApplication.mLocationService != null) {
            MyApplication.mLocationService.start();
        }
    }
    /*****
     *
     * 定位结果回调，重写onReceiveLocation方法，可以直接拷贝如下代码到自己工程中修改
     *
     */
    private BDAbstractLocationListener mListener = new BDAbstractLocationListener() {

        /**
         * 定位请求回调函数
         *
         * @param location 定位结果
         */
        @Override
        public void onReceiveLocation(BDLocation location) {
            if (null != location && location.getLocType() != BDLocation.TypeServerError &&
                    location.getLocType() != BDLocation.TypeOffLineLocationFail &&
                    location.getLocType() != BDLocation.TypeCriteriaException) {
                StringBuffer sb = new StringBuffer(256);
                sb.append("定位成功");
                sb.append("time : ");
                /**
                 * 时间也可以使用systemClock.elapsedRealtime()方法 获取的是自从开机以来，每次回调的时间；
                 * location.getTime() 是指服务端出本次结果的时间，如果位置不发生变化，则时间不变
                 */
                String locationTime = location.getTime();
                sb.append(locationTime);
            //   String netLocType = location.getNetworkLocationType();
              //  sb.append(getNetworkLocationType(location.getNetworkLocationType()));
                sb.append("\nlocType : ");// 定位类型
                int locType = location.getLocType();
                sb.append(locType);
                sb.append("\nlocType description : ");// *****对应的定位类型说明*****
                sb.append(location.getLocTypeDescription());
                sb.append("\nlatitude : ");// 纬度
                mLat = location.getLatitude();
                sb.append(mLat);
                sb.append("\nlongtitude : ");// 经度
                mLng = location.getLongitude();
                sb.append(mLng);
                sb.append("\nradius : ");// 半径
                sb.append(location.getRadius());
                sb.append("\nCountryCode : ");// 国家码
                sb.append(location.getCountryCode());
                sb.append("\nProvince : ");// 获取省份
                sb.append(location.getProvince());
                sb.append("\nCountry : ");// 国家名称
                sb.append(location.getCountry());
                sb.append("\ncitycode : ");// 城市编码
                sb.append(location.getCityCode());
                sb.append("\ncity : ");// 城市
                sb.append(location.getCity());
                sb.append("\nDistrict : ");// 区
                sb.append(location.getDistrict());
                sb.append("\nTown : ");// 获取镇信息
                sb.append(location.getTown());
                sb.append("\nStreet : ");// 街道
                sb.append(location.getStreet());
                sb.append("\naddr : ");// 地址信息
                sb.append(location.getAddrStr());
                EventBus.getDefault().post(location);
                MyLogFile.i(TAG,"latitude="+mLat+",longtitude="+mLng+",locType="+locType+",locTime="+locationTime);
                long locationTimeStamp = DateTimeUtils.toTimeStamp(locationTime,0);
                long postTime = System.currentTimeMillis(); //由于位置没变化时，GPS定位时间也不变化。所以为了更新时间给服务器，上传的是手机系统时间。
                //发送位置
                boolean isAllow = isAllowLocation();
                if(isAllow){
                    SocketManager.getInstance(getApplicationContext()).sendLocationPack(mLat,mLng,postTime);
                }
            }
        }




        /**
         * 回调定位诊断信息，开发者可以根据相关信息解决定位遇到的一些问题
         * @param locType 当前定位类型
         * @param diagnosticType 诊断类型（1~9）
         * @param diagnosticMessage 具体的诊断信息释义
         */
        @Override
        public void onLocDiagnosticMessage(int locType, int diagnosticType,
                                           String diagnosticMessage) {
            super.onLocDiagnosticMessage(locType, diagnosticType, diagnosticMessage);
            StringBuffer sb = new StringBuffer(256);
            sb.append("locType:" + locType);
            sb.append("\n" + "诊断结果: ");
            if (locType == BDLocation.TypeNetWorkLocation) {
                if (diagnosticType == 1) {
                    sb.append("网络定位成功，没有开启GPS，建议打开GPS会更好" + "\n");
                    sb.append(diagnosticMessage);
                } else if (diagnosticType == 2) {
                    sb.append("网络定位成功，没有开启Wi-Fi，建议打开Wi-Fi会更好" + "\n");
                    sb.append(diagnosticMessage);
                }
            } else if (locType == BDLocation.TypeOffLineLocationFail) {
                if (diagnosticType == 3) {
                    sb.append("定位失败，请您检查您的网络状态" + "\n");
                    sb.append(diagnosticMessage);
                }
            } else if (locType == BDLocation.TypeCriteriaException) {
                if (diagnosticType == 4) {
                    sb.append("定位失败，无法获取任何有效定位依据" + "\n");
                    sb.append(diagnosticMessage);
                } else if (diagnosticType == 5) {
                    sb.append("定位失败，无法获取有效定位依据，请检查运营商网络或者Wi-Fi网络是否正常开启，尝试重新请求定位" + "\n");
                    sb.append(diagnosticMessage);
                } else if (diagnosticType == 6) {
                    sb.append("定位失败，无法获取有效定位依据，请尝试插入一张sim卡或打开Wi-Fi重试" + "\n");
                    sb.append(diagnosticMessage);
                } else if (diagnosticType == 7) {
                    sb.append("定位失败，飞行模式下无法获取有效定位依据，请关闭飞行模式重试" + "\n");
                    sb.append(diagnosticMessage);
                } else if (diagnosticType == 9) {
                    sb.append("定位失败，无法获取任何有效定位依据" + "\n");
                    sb.append(diagnosticMessage);
                }
            } else if (locType == BDLocation.TypeServerError) {
                if (diagnosticType == 8) {
                    sb.append("定位失败，请确认您定位的开关打开状态，是否赋予APP定位权限" + "\n");
                    sb.append(diagnosticMessage);
                }
            }
            MyLogCat.i(TAG,sb.toString());
        }
    };
    /**
     * 是否允许定位
     * @return true 允许定位
     */
    public boolean isAllowLocation(){
        String isLocation =  (!TextUtils.isEmpty(MyApplication.mIsUplocation)) ? MyApplication.mIsUplocation:
                SPUtils.getString(getApplicationContext(),"isLocation");
        String weightState =  (!TextUtils.isEmpty(MyApplication.mWeighsStatus)) ? MyApplication.mWeighsStatus
                :SPUtils.getString(getApplicationContext(),"weightState");

        if("1".equals(isLocation) && "3".equals(weightState)){
            return true;
        }
        return false;
    }

    /**
     * 在网络定位结果的情况下，获取网络定位结果是通过基站定位得到的还是通过wifi定位得到的还是GPS得结果
     *
     * @param networkLocationType location.getNetworkLocationType()
     * @return 定位结果类型
     */
    private String getNetworkLocationType(String networkLocationType){
        String str = "";
        switch (networkLocationType){
            case "wf":
                str = "wifi定位结果";
                break;
            case "cl":
                str = "基站定位结果";
                break;
            case "ll":
                str = "GPS定位结果";
                break;
            case "":
                str = "没有获取到定位结果采用的类型";
                break;
        }
        return str;
    }



    /**
     * 解决androidP 第一次打开程序出现弹窗
     * 弹窗内容“detected problems with api ”
     */
    private void closeAndroidPDialog(){
        try {
            Class aClass = Class.forName("android.content.pm.PackageParser$Package");
            Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class);
            declaredConstructor.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Class cls = Class.forName("android.app.ActivityThread");
            Method declaredMethod = cls.getDeclaredMethod("currentActivityThread");
            declaredMethod.setAccessible(true);
            Object activityThread = declaredMethod.invoke(null);
            Field mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown");
            mHiddenApiWarningShown.setAccessible(true);
            mHiddenApiWarningShown.setBoolean(activityThread, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 监听到wifi&移动网络切换时，重连服务器
     */
    public class NetworkChange extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo mobNetInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            NetworkInfo wifiNetInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

            if (!mobNetInfo.isConnected() && !wifiNetInfo.isConnected()) {
                MyLogFile.i(TAG, "tcpclient in application网络不可以用");
            } else if (mobNetInfo.isConnected() || wifiNetInfo.isConnected()) {
                MyLogFile.i(TAG, "tcpclient in application 网络发生了切换断开，需要重连服务器.");

                boolean isAllow = isAllowLocation();
                if(isAllow){
                    SocketManager socketManager = SocketManager.getInstance(getApplicationContext());
                    socketManager .setConnServer(false);
                    socketManager.connectServer();
                }

            }
        }
    }

    /**
     * 保存当前任务ID到缓存，供其它页面使用，如地图页面。
     * @param taskId
     */
    public void saveCurTask(Context context,String taskId,String isLocation,String weighsStatus) {
        MyApplication.mCurTaskId = taskId;
        MyApplication.mIsUplocation = isLocation;
        MyApplication.mWeighsStatus = weighsStatus;
        if(context != null){
            SPUtils.putCurTask(context,taskId,isLocation,weighsStatus);
        }
    }



    /**
     * 初始化ImageLoader图片加载框架
     * @param context
     */
    public static void initImageLoader(Context context) {
        // 缓存文件的目录
        File cacheDir = StorageUtils.getOwnCacheDirectory(context,
                PIC_DIRECTORY);
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
                context)
                // 即保存的每个缓存文件的最大长宽
                // 线程池内加载的数量
                .memoryCacheExtraOptions(480, 800)
                .threadPriority(Thread.NORM_PRIORITY - 2)
                .denyCacheImageMultipleSizesInMemory()
                // 线程池内加载的数量
                .threadPoolSize(3)
                // 将保存的时候的URI名称用MD5 加密
                .diskCacheFileNameGenerator(new Md5FileNameGenerator())
                // 你可以通过自己的内存缓存实现
                .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
                // 内存缓存的最大值
                .memoryCacheSize(2 * 1024 * 1024)
                // 50 Mb sd卡(本地)缓存的最大值
                .diskCacheSize(50 * 1024 * 1024)
                .tasksProcessingOrder(QueueProcessingType.LIFO)
                // 由原先的discCache -> diskCache
                // 自定义缓存路径
                .diskCache(new UnlimitedDiskCache(cacheDir))
                // 5s,30s超时时间
                .imageDownloader(
                        new BaseImageDownloader(context, 5 * 1000, 30 * 1000))
                // Remove for release app
                .writeDebugLogs().build();
        // 全局初始化此配置
        ImageLoader.getInstance().init(config);
    }
    public static DisplayImageOptions options = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.login_head)
            // 设置图片下载期间显示的图片
            .showImageForEmptyUri(R.drawable.login_head)
            // 设置图片Uri为空或是错误的时候显示的图片
            .showImageOnFail(R.drawable.login_head)
            // 设置图片加载或解码过程中发生错误显示的图片
            .resetViewBeforeLoading(true)
            // 设置延迟部分时间才开始加载
            .imageScaleType(ImageScaleType.EXACTLY)
            // 设置图片的缩放方式
            .bitmapConfig(Bitmap.Config.RGB_565).considerExifParams(true)
            .cacheInMemory(true) // 设置下载的图片是否缓存在内存中
            .cacheOnDisk(true) // 设置下载的图片是否缓存在SD卡中
            .displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片
            .displayer(new FadeInBitmapDisplayer(500))
            .build();
}
